<?php

namespace common\helpers;

use yii\helpers\BaseStringHelper;
use yii\helpers\Json;

/**
 * 字符串扩展操作函数
 *
 * @author emhome <emhome@163.com>
 * @since 1.0
 */
class StringHelper extends BaseStringHelper {

    const PATTERN_MOBILE = '/1[3456789]{1}\d{9}$/';
    const PATTERN_EMAIL = '/^\w+([-.]\w+)*@([0-9a-z][0-9a-z-]+.)+[a-z]{2,3}$/';
    const PATTERN_IDCARDNO = '/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|x|X)$/';

    /**
     * 生成随机字符串
     *
     * @param int $length 长度
     * @param boolean $numeric 是否返回数字
     * @return string 字符串
     */
    public static function random($length, $numeric = false) {
        $source = microtime();
        if (is_string($_SERVER['DOCUMENT_ROOT'])) {
            $source .= strval($_SERVER['DOCUMENT_ROOT']);
        }
        $hash = '';
        $string = '';
        if ($numeric) {
            $seed = base_convert(md5($source), 16, 10);
            $string = str_replace('0', '', $seed) . '012340567890';
        } else {
            $seed = base_convert(md5($source), 16, 35);
            $string = $seed . 'zZ' . strtoupper($seed);
            $hash = chr(rand(1, 26) + rand(0, 1) * 32 + 64);
            $length--;
        }
        $max = strlen($string) - 1;
        for ($i = 0; $i < $length; $i++) {
            $hash .= $string{mt_rand(0, $max)};
        }
        return $hash;
    }

    /**
     * 屏蔽字符串的一部分字符为指定字符
     * 
     * @param string $subject 字符串
     * @param integer $start 开始位置
     * @param integer $end 结束位置
     * @param string $char 替换字符
     * @param string $type 正则表达式
     * @return string
     */
    public static function maskChar($subject, $start = 3, $end = 4, $char = '*', $type = 'w') {
        $length = static::byteLength($subject);
        $masklength = $length - $start - $end;
        //\w
        $pattern_begin = '(\\' . $type . '{0,' . $start . '})';
        $pattern_end = '(\\' . $type . '{' . $end . '})';
        $pattern_body = '\\' . $type . '{' . $masklength . '}';
        $pattern = '/' . $pattern_begin . $pattern_body . $pattern_end . '/';
        $replacement = "\$1 " . str_pad('', $masklength, $char) . " \$2";
        return preg_replace($pattern, $replacement, $subject);
    }

    public static function matchEmoticon($content) {
        $pattern = "/\[([\x{4e00}-\x{9fa5}a-zA-Z0-9]+)\]/use";
        if (preg_match_all($pattern, $content, $matches)) {
            return $matches[1];
        }
        return [];
    }

    /**
     * 移除emoji标签
     * @param string $text
     * @return string
     */
    public static function removeEmoji($text) {
        $patterns = [
            '/[\x{1F600}-\x{1F64F}]/u',
            '/[\x{1F300}-\x{1F5FF}]/u',
            '/[\x{1F680}-\x{1F6FF}]/u',
            '/[\x{2600}-\x{26FF}]/u',
            '/[\x{2700}-\x{27BF}]/u',
        ];
        return preg_replace($patterns, '', $text);
    }

    /**
     * 十六进制转RGB
     * 
     * @param string $color 16进制颜色值
     * @return array
     */
    public static function hex2rgb($color) {
        $hexColor = str_replace('#', '', $color);
        $lens = strlen($hexColor);
        if ($lens != 3 && $lens != 6) {
            return false;
        }
        $newcolor = '';
        if ($lens == 3) {
            for ($i = 0; $i < $lens; $i++) {
                $newcolor .= $hexColor[$i] . $hexColor[$i];
            }
        } else {
            $newcolor = $hexColor;
        }
        $hex = str_split($newcolor, 2);
        $rgb = [];
        foreach ($hex as $key => $vls) {
            $rgb[] = hexdec($vls);
        }
        return $rgb;
    }

    /**
     * 正则表达式检测已有类型数据格式
     * 
     * @param string $content 检测内容
     * @param string $pattern 正则表达式
     * @return boolean 检测状态
     */
    public static function formatContent($content, $pattern) {
        if (preg_match($pattern, $content)) {
            return true;
        }
        return false;
    }

    /**
     * 检测手机号是否正确
     * 
     * @param string $text 检测内容
     * @return boolean 
     */
    public static function isMobile($text) {
        $formatPattern = Yii::$app->params['format_pattern'];
        $pattern = isset($formatPattern['mobile']) ? $formatPattern['mobile'] : self::PATTERN_MOBILE;
        return self::formatContent($text, $pattern);
    }

    /**
     * 检测邮箱是否正确
     * 
     * @param string $text 检测内容
     * @return boolean 
     */
    public static function isEmail($text) {
        $formatPattern = Yii::$app->params['format_pattern'];
        $pattern = isset($formatPattern['email']) ? $formatPattern['email'] : self::PATTERN_EMAIL;
        return self::formatContent($text, $pattern);
    }

    /**
     * 检测身份证号是否正确
     * 
     * @param string $value 检测内容
     * @return boolean 检测状态
     */
    public static function isIdcardNumber($value, $exact = true) {
        if (!$exact) {
            $formatPattern = Yii::$app->params['format_pattern'];
            $pattern = isset($formatPattern['idcardno']) ? $formatPattern['idcardno'] : self::PATTERN_IDCARDNO;
            return self::formatContent($text, $pattern);
        }
        $provinceNumber = array(
            '11', '12', '13', '14', '15', '21', '22',
            '23', '31', '32', '33', '34', '35', '36',
            '37', '41', '42', '43', '44', '45', '46',
            '50', '51', '52', '53', '54', '61', '62',
            '63', '64', '65', '71', '81', '82', '91'
        );
        if (!preg_match('/^([\d]{17}[xX\d]|[\d]{15})$/', $value)) {
            return false;
        }
        if (!in_array(substr($value, 0, 2), $provinceNumber)) {
            return false;
        }
        $value = preg_replace('/[xX]$/i', 'a', $value);
        $length = strlen($value);
        if ($length == 18) {
            $birthday = substr($value, 6, 4) . '-' . substr($value, 10, 2) . '-' . substr($value, 12, 2);
        } else {
            $birthday = '19' . substr($value, 6, 2) . '-' . substr($value, 8, 2) . '-' . substr($value, 10, 2);
        }
        if (date('Y-m-d', strtotime($birthday)) != $birthday) {
            return false;
        }
        if ($length == 18) {
            $_sum = 0;
            for ($i = 17; $i >= 0; $i--) {
                $_subs = substr($value, 17 - $i, 1);
                $_sum += (pow(2, $i) % 11) * (($_subs == 'a') ? 10 : intval($_subs, 11));
            }
            if ($_sum % 11 != 1) {
                return false;
            }
        }
        return true;
    }

    /**
     * 数字转换为中文
     * @param  string|integer|float  $num  目标数字
     * @param  integer $mode 模式[true:金额（默认）,false:普通数字表示]
     * @param  boolean $sim 使用小写（默认）
     * @return string
     */
    function numberToZhcn($num, $mode = true, $sim = true) {
        if (!is_numeric($num)) {
            return '含有非数字非小数点字符！';
        }
        $char = $sim ? array('零', '一', '二', '三', '四', '五', '六', '七', '八', '九') : array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖');
        $unit = $sim ? array('', '十', '百', '千', '', '万', '亿', '兆') : array('', '拾', '佰', '仟', '', '萬', '億', '兆');
        $retval = $mode ? '元' : '点';
        //小数部分
        if (strpos($num, '.')) {
            list($num, $dec) = explode('.', $num);
            $dec = strval(round($dec, 2));
            if ($mode) {
                $retval .= "{$char[$dec['0']]}角{$char[$dec['1']]}分";
            } else {
                for ($i = 0, $c = strlen($dec); $i < $c; $i++) {
                    $retval .= $char[$dec[$i]];
                }
            }
        }
        //整数部分
        $str = $mode ? strrev(intval($num)) : strrev($num);
        for ($i = 0, $c = strlen($str); $i < $c; $i++) {
            $out[$i] = $char[$str[$i]];
            if ($mode) {
                $out[$i] .= $str[$i] != '0' ? $unit[$i % 4] : '';
                if ($i > 1 and $str[$i] + $str[$i - 1] == 0) {
                    $out[$i] = '';
                }
                if ($i % 4 == 0) {
                    $out[$i] .= $unit[4 + floor($i / 4)];
                }
            }
        }
        $retval = join('', array_reverse($out)) . $retval;
        return $retval;
    }

    public function unicodeDecode($string) {
        $json = '{"str":"' . $string . '"}';
        $arr = Json::decode($json);
        if (empty($arr)) {
            return '';
        }
        return $arr['str'];
    }

}
